﻿using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Com.ZX.View;
using FairyGUI;

namespace Com.ZX.Manager
{
    public class UIManager : BaseSingleton<UIManager>
    {
        public UIManager()
        {

        }

        private EnumUIType currentOpenedUI = EnumUIType.MAX_COUNT;

        //需要一个导航UI栈，

        /// <summary>
        /// 已经打开的UI集合
        /// </summary>
        private Dictionary<EnumUIType, System.Object> dictOpenedUIs = null;
        /// <summary>
        /// 待打开的UI栈
        /// </summary>
        private Stack<UIInfoData> stackWillOpenUIs = null;
        /// <summary>
        /// 导航栈
        /// </summary>
        private Stack<EnumUIType> stackNavigationUIs = null;

        //private Stack<>
        public override void onInit()
        {
            dictOpenedUIs = new Dictionary<EnumUIType, System.Object>();
            stackWillOpenUIs = new Stack<UIInfoData>();
            stackNavigationUIs = new Stack<EnumUIType>();
        }

        /// <summary>
        /// 获取UIObject组件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="uiType"></param>
        /// <returns></returns>
        public T GetUI<T>(EnumUIType uiType) where T : IView
        {
#if USE_FAIRYGUI
            T wind = (T)GetUIObject(uiType);
            if (wind != null)
                return wind;
#else
            GameObject ui = (GameObject)GetUIObject(uiType);
            if (obj != null)
                return obj.GetComponent<T>();
#endif

            return default(T);
        }

        /// <summary>
        /// 获取UIObject
        /// </summary>
        /// <param name="uiType"></param>
        /// <returns></returns>
        public System.Object GetUIObject(EnumUIType uiType)
        {
            System.Object obj = null;
            if (!dictOpenedUIs.TryGetValue(uiType, out obj))
            {
                OpenUI(uiType);
                while (!dictOpenedUIs.TryGetValue(uiType, out obj))
                {
                    CustomDebug.Log("循环...");
                }
                //throw new Exception("not found the UI :" + uiType.ToString() + "in the UI list!");
            }
            return obj;
        }

        /// <summary>
        /// 打开多个UI
        /// </summary>
        /// <param name="uiTypes"></param>
        public void OpenUI(EnumUIType[] uiTypes)
        {
            OpenUI(false, uiTypes, null);
        }

        /// <summary>
        /// 打开单个UI
        /// </summary>
        /// <param name="uiType"></param>
        /// <param name="uiParams"></param>
        public void OpenUI(EnumUIType uiType, params object[] uiParams)
        {
            EnumUIType[] uiTypes = new EnumUIType[1];
            uiTypes[0] = uiType;
            OpenUI(false, uiTypes, uiParams);
        }

        /// <summary>
        /// 打开多个UI，关闭其他UI
        /// </summary>
        /// <param name="uiTypes"></param>
        public void OpenUICloseOther(EnumUIType[] uiTypes)
        {
            OpenUI(true, uiTypes, null);
        }

        /// <summary>
        /// 打开单个UI,关闭其他UI
        /// </summary>
        /// <param name="uiType"></param>
        /// <param name="uiParams"></param>
        public void OpenUICloseOther(EnumUIType uiType, params object[] uiParams)
        {
            EnumUIType[] uiTypes = new EnumUIType[1];
            uiTypes[0] = uiType;
            OpenUI(true, uiTypes, uiParams);
        }

        public void OpenUIHideCurrent(EnumUIType uiType, params object[] uiParams)
        {
            EnumUIType[] uiTypes = new EnumUIType[1];
            uiTypes[0] = uiType;
            HideUIinNavigation(currentOpenedUI);
            OpenUI(false, uiTypes, uiParams);
        }

        /// <summary>
        /// 打开多个UI
        /// </summary>
        /// <param name="isCloseOtherUI"></param>
        /// <param name="uiType"></param>
        /// <param name="uiParams"></param>
        public void OpenUI(bool isCloseOtherUI, EnumUIType[] uiTypes, params object[] uiParams)
        {
            if (isCloseOtherUI)
            {
                // to do
                //close other ui
                CloseAllUI();
            }

            for (int i = 0; i < uiTypes.Length; i++)
            {
                EnumUIType type = uiTypes[i];
                if (!dictOpenedUIs.ContainsKey(type))
                {
                    //to do
                    //add this ui type to stackWillOpenUIs
                    string path = UIDefine.GetUIPathByType(type);
                    stackWillOpenUIs.Push(new UIInfoData(type, path, uiParams));
                }
            }

            if (stackWillOpenUIs.Count > 0)
            {
                //to do
                //open ui with stackWillOpenUIs
                MonoControlHelper.inst.StartCoroutine(AsyncLoadData());

                //ResrManager._Instance
            }
        }

        //AsyncOperation m_asyn;
        /// <summary>
        /// 异步加载
        /// </summary>
        /// <returns></returns>
        private IEnumerator<int> AsyncLoadData()
        {
            UIInfoData _uiInfo = null;
            //UIInfoData uiInfo = null;
            //UnityEngine.Object _uiPrefab = null;
            //GameObject _uiObj = null;
            Window uiObj = null;
            while (stackWillOpenUIs != null && stackWillOpenUIs.Count > 0)
            {
                //需要ResourcesMannager
                _uiInfo = stackWillOpenUIs.Pop();

#if USE_FAIRYGUI
                uiObj = ResrManager.inst.LoadInstance<Window>(_uiInfo);
                if (uiObj != null)
                {
                    uiObj.Show();
                    dictOpenedUIs.Add(_uiInfo.UIType, uiObj);
                    currentOpenedUI = _uiInfo.UIType; //设置当前UIType，导航UI用到
                }
#else
                _uiObj = (GameObject)ResrManager.inst.LoadInstance(_uiInfo.Path);
                CustomDebug.Log(_uiObj.name);
                IView _baseUI = _uiObj.GetComponent<IView>();
                if (_baseUI != null)
                {
                    //_baseUI.SetUIWhenUIOpen(_uiInfo.UIParams);
                    dictOpenedUIs.Add(_uiInfo.UIType, _uiObj);
                    currentOpenedUI = _uiInfo.UIType; //设置当前UIType，导航UI用到

                }
#endif
                uiObj = null;
               //CustomDebug.Log(dictOpenedUIs.Count());
            }
            yield return 0;
        }

        public void ShowUIinNavigation()
        {
            EnumUIType targetUIType = stackNavigationUIs.Pop();
            HideUI(currentOpenedUI);
            ShowUI(targetUIType);
            currentOpenedUI=targetUIType;
        }

        public void ShowUI(EnumUIType uiType)
        {
#if USE_FAIRYGUI
            Window wind = (Window)GetUIObject(uiType);
            wind.Show();
#else
            GameObject uiGo = (GameObject)GetUIObject(uiType);
            uiGo.SetActive(true);
            uiGo = null;
#endif
        }

        public void HideUIinNavigation(EnumUIType uiType)
        {
            stackNavigationUIs.Push(uiType);
            HideUI(uiType);
        }

        public void HideUI(EnumUIType uiType)
        {
#if USE_FAIRYGUI
            Window wind = (Window)GetUIObject(uiType);
            wind.Hide();
#else
            GameObject uiGo = (GameObject)GetUIObject(uiType);
            uiGo.SetActive(false);
            uiGo = null;
#endif
        }

        /// <summary>
        /// 关闭所有UI
        /// </summary>
        public void CloseAllUI()
        {
            List<EnumUIType> uiTypeList = dictOpenedUIs.Keys.ToList();
            for (int i = 0; i < uiTypeList.Count; i++)
                CloseUI(uiTypeList[i]);
            dictOpenedUIs.Clear();
            uiTypeList = null;
        }

        /// <summary>
        /// 关闭一组UI
        /// </summary>
        /// <param name="uiTypes"></param>
        public void CloseUI(EnumUIType[] uiTypes)
        {
            for (int i = 0; i < uiTypes.Length; i++)
                CloseUI(uiTypes[i]);
        }

        /// <summary>
        /// 关闭UI
        /// </summary>
        /// <param name="uiType"></param>
        public void CloseUI(EnumUIType uiType)
        {
#if USE_FAIRYGUI
            IView uiObj = (IView)GetUIObject(uiType);
            if (uiObj != null)
            {
                uiObj.StateChanged += CloseUIHandler;
                uiObj.Release();
            }
#else
            GameObject uiObj = (GameObject)GetUIObject(uiType);
            
            if (uiObj == null)
            {
                dictOpenedUIs.Remove(uiType);
            }
            else
            {
                IView baseUI = uiObj.GetComponent<IView>();
                if (baseUI == null)
                {
                    GameObject.Destroy((UnityEngine.Object)baseUI);
                    dictOpenedUIs.Remove(uiType);
                }
                else
                {
                    baseUI.StateChanged += CloseUIHandler;
                    baseUI.Release();
                }
            }
#endif
        }

        private void CloseUIHandler(object ui, EnumObjState newState, EnumObjState oldState)
        {
            if (newState == EnumObjState.Closed)
            {
                IView baseUI = (IView)ui;
                dictOpenedUIs.Remove(baseUI.GetUIType());
                baseUI.StateChanged -= CloseUIHandler;
            }
        }
    }

    public class UIInfoData
    {
        public EnumUIType UIType { get; private set; }
        public string Path { get; private set; }
        public object[] UIParams { get; private set; }

        public UIInfoData(EnumUIType _uiType, string _path, params object[] _uiParams)
        {
            this.UIType = _uiType;
            this.Path = _path;
            this.UIParams = _uiParams;
        }
    }
}
